#include "Minimap.h"
#include "GLPrimitives.h"
#include "General Utils.hpp"
#include "ImageLoader.hpp"
#include "GameWorld.h"

// Constructor
Minimap::Minimap()
{
	m_pClipPlane = ClipPlane;
	m_Texture = -1;
	m_TextureRatio = 1;
	// simply give standard values to a bunch of variables
	m_TextureDimensions.w = 150;
	m_TextureDimensions.h = 150;
	m_OriginalDimensions = m_TextureDimensions;
	m_SurroundDistance = 5;

	m_TextureClippingPercentage.x = 1.0;
	m_TextureClippingPercentage.y = 1.0;

	m_MapDimensions.w = 100;
	m_MapDimensions.h = 100;

	m_TexturePosition.x = 10;
	m_TexturePosition.y = DataLoader->WINDOW_HEIGHT - m_TextureDimensions.h - 10;
	m_OriginalPosition = m_TexturePosition;

	m_IsBuilt = false;
}

Minimap::Minimap(ClippingPlane *pClippingPlane)
{
	m_pClipPlane = ClipPlane;
	m_Texture = -1;
	m_TextureRatio = 1;
	// simply give standard values to a bunch of variables
	m_TextureDimensions.w = 150;
	m_TextureDimensions.h = 150;
	m_OriginalDimensions = m_TextureDimensions;
	m_SurroundDistance = 5;

	m_MapDimensions.w = 100;
	m_MapDimensions.h = 100;

	m_TextureClippingPercentage.x = 1.0;
	m_TextureClippingPercentage.y = 1.0;

	
	m_TexturePosition.x = 10;
	m_TexturePosition.y = DataLoader->WINDOW_HEIGHT - m_TextureDimensions.h - 10;
	m_OriginalPosition = m_TexturePosition;

	m_IsBuilt = false;
	m_pClipPlane = pClippingPlane;
}

// Texture Handling
void Minimap::Load(const string &filename)
{
	// free memory if necessary
	Delete();

	// map_filename -------------------------------------------------
	// Open the level file
	ifstream mapFile;
	mapFile.open(filename.c_str());
	assert("Unable to load level for minimap " && mapFile);

	// get map width / height
	mapFile >> m_MapDimensions.w >> m_MapDimensions.h;
	
	// setup the texture ratio
	m_TextureRatio = (float)m_MapDimensions.h / (float)m_MapDimensions.w;

	// height / width
	vector<vector<int>> aMap;
	vector<int> usedTiles;

	// resize the map

	aMap.reserve(m_MapDimensions.h*m_MapDimensions.w);
	aMap.resize(m_MapDimensions.h);
	for(int h = 0; h < m_MapDimensions.h; ++h)
	{
		aMap[h].reserve(m_MapDimensions.w);
		aMap[h].resize(m_MapDimensions.h);
	}

	// read map data
	char buffer[100];
	for(int h = 0; h < m_MapDimensions.h; h++)
		for(int w = 0; w < m_MapDimensions.h; w++)
		{
			// get our tile
			mapFile >> aMap[h][w];
			mapFile.getline(buffer, 100, '->');

			// if this tile has not already been added to used tiles then add it
			bool insert = true;
			for(vector<int>::const_iterator iter = usedTiles.begin(); iter != usedTiles.end(); ++iter)
				if(aMap[h][w] == *iter)
					insert = false;

			if(insert)
				usedTiles.push_back(aMap[h][w]);
		}
	
	mapFile.close();
	// map_filename -------------------------------------------------

	// load in minimap data
	std::map<int, ImageLoader::MinimapData>	minimapData;
	for(int i = 0; i < usedTiles.size(); ++i)
	{
		minimapData.insert(std::pair<int, ImageLoader::MinimapData>(usedTiles[i],
				(*(ImageManager->GetMinimapData(usedTiles[i])))));
	}
	

	// Create the texture and make it black
	SDL_PixelFormat RGBAFormat = GetPixelFormat();
	SDL_Surface* texture = SDL_CreateRGBSurface( SDL_SWSURFACE, GetNextPowerOfTwo(m_MapDimensions.w), GetNextPowerOfTwo(m_MapDimensions.h), RGBAFormat.BitsPerPixel,
		RGBAFormat.Rmask, RGBAFormat.Gmask, RGBAFormat.Bmask, RGBAFormat.Amask );
	SDL_FillRect(texture, NULL, SDL_MapRGB((const SDL_PixelFormat *const)&RGBAFormat, 255, 255, 255));

	// lock the texture
	if( SDL_MUSTLOCK( texture ) )
        SDL_LockSurface( texture );

	// Create the new minimap texture
	for(int y = 0; y < m_MapDimensions.h; ++y)
		for(int x = 0; x < m_MapDimensions.w; ++x)	
		{
			// Read the pixel from the grid
			// We only care about layer 0
			int r, g, b;

			r = (int)(minimapData[aMap[y][x]].r * 255);
			g = (int)(minimapData[aMap[y][x]].g * 255);
			b = (int)(minimapData[aMap[y][x]].b * 255);

			// apply a smoothing algorithm
			int rl = 0, rt = 0, rr = 0, rb = 0; // red left, red top, red right, red bottom
			int gl = 0, gt = 0, gr = 0, gb = 0; // green left, green top, green right, green bottom
			int bl = 0, bt = 0, br = 0, bb = 0; // blue left, blue top, blue right, blue bottom

			// get colors
			if(x > 0)
			{
				rl = (int)(minimapData[aMap[y][x-1]].r * 255);
				gl = (int)(minimapData[aMap[y][x-1]].g * 255);
				bl = (int)(minimapData[aMap[y][x-1]].b * 255);
			}

			if(y > 0)
			{
				rt = (int)(minimapData[aMap[y-1][x]].r * 255);
				gt = (int)(minimapData[aMap[y-1][x]].g * 255);
				bt = (int)(minimapData[aMap[y-1][x]].b * 255);
			}

			if(x < m_MapDimensions.w - 1)
			{
				rr = (int)(minimapData[aMap[y][x+1]].r * 255);
				gr = (int)(minimapData[aMap[y][x+1]].g * 255);
				br = (int)(minimapData[aMap[y][x+1]].b * 255);
			}
			
			if(y < m_MapDimensions.h - 1)
			{
				rb = (int)(minimapData[aMap[y+1][x]].r * 255);
				gb = (int)(minimapData[aMap[y+1][x]].g * 255);
				bb = (int)(minimapData[aMap[y+1][x]].b * 255);
			}
			
			// Now, we actually smooth the minimap by multiplying the source pixel by a percentage of its surrounding pixels
			float mix = .2;
			r += ((rl + rt + rr + rb) * mix);
			b += ((bl + bt + br + bb) * mix);
			g += ((gl + gt + gr + gb) * mix);

			// SDL doesn't like pixels over 255; ensure they are not over 255
			if(r > 255) r = 255;
			if(b > 255) b = 255;
			if(g > 255) g = 255;

			// Get our color
			Uint32 color = SDL_MapRGB(texture->format, r, g, b);
			
			// put these pixels on the screen
			Uint32 *pixels = (Uint32 *)texture->pixels;
			pixels[ ( y * texture->w ) + x ] = color;

		}

	// unlock the texture
	if( SDL_MUSTLOCK( texture ) )
        SDL_UnlockSurface( texture );



	// Convert the texture to an openGL texture
	//-------------------------------------------------------

	// Convert the surface to a format readable by openGL
	// Basic declarations
	GLenum texture_format;
	GLint nOfColors;	
	
	// get the number of channels in the SDL surface
    nOfColors = texture->format->BytesPerPixel;
    if (nOfColors == 4)     // contains an alpha channel
    {
            if (texture->format->Rmask == 0x000000ff)
                    texture_format = GL_RGBA;
            else
                    texture_format = GL_BGRA;
    } else if (nOfColors == 3)     // no alpha channel
    {
            if (texture->format->Rmask == 0x000000ff)
                    texture_format = GL_RGB;
            else
                    texture_format = GL_BGR;
    } else {
            assert("Loaded image is not truecolor" && false);
    }



	// Have OpenGL generate a texture object handle for us
	glGenTextures( 1, &m_Texture );
 
	// Bind the texture object
	glBindTexture( GL_TEXTURE_2D, m_Texture );
 
	// Set the texture's stretching properties
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 
	// Edit the texture object's image data using the information SDL_Surface gives us
	glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, texture->w, texture->h, 0,
                      texture_format, GL_UNSIGNED_BYTE, texture->pixels );



	// Free memory
	SDL_FreeSurface(texture);

	// We have built the texture
	m_IsBuilt = true;

	// Compute texture position / location
	RecomputeTexturePosition();
	
	// Set up our texture clipping percentages
	m_TextureClippingPercentage.x = double(m_MapDimensions.w) / double(GetNextPowerOfTwo(m_MapDimensions.w));
	m_TextureClippingPercentage.y = double(m_MapDimensions.h) / double(GetNextPowerOfTwo(m_MapDimensions.h));
}

// Create a minimap texture from a room
void Minimap::Load(const Room& room)
{	
	int ignored = ImageManager->GetImageID("ignored_tile");
	vector<int> usedTiles;
	usedTiles.reserve(20);
	

	// resize the map
	// read map data
	for(int h = 0; h < room.h; h++)
		for(int w = 0; w < room.w; w++)
		{
			// if this tile has not already been added to used tiles then add it
			bool insert = true;
			for(vector<int>::const_iterator iter = usedTiles.begin(); iter != usedTiles.end(); ++iter)
				if(room.tiles[h][w][0] == *iter)
					insert = false;

			if(insert)
				usedTiles.push_back(room.tiles[h][w][0]);
		}

	// load in minimap data
	std::map<int, ImageLoader::MinimapData>	minimapData;
	for(int i = 0; i < usedTiles.size(); ++i)
	{
		minimapData.insert(std::pair<int, ImageLoader::MinimapData>(usedTiles[i],
				(*(ImageManager->GetMinimapData(usedTiles[i])))));
	}
	

	// Create the texture and make it black
	SDL_PixelFormat RGBAFormat = GetPixelFormat();
	SDL_Surface* texture = SDL_CreateRGBSurface( SDL_SWSURFACE, GetNextPowerOfTwo(m_MapDimensions.w), GetNextPowerOfTwo(m_MapDimensions.h), RGBAFormat.BitsPerPixel,
		RGBAFormat.Rmask, RGBAFormat.Gmask, RGBAFormat.Bmask, RGBAFormat.Amask );
	//SDL_FillRect(texture, NULL, SDL_MapRGBA((const SDL_PixelFormat *const)&RGBAFormat, 255, 255, 255, 0));

	

	// lock the texture
	if( SDL_MUSTLOCK( texture ) )
        SDL_LockSurface( texture );

	// Create the new minimap texture
	for(int y = 0; y < room.h; ++y)
		for(int x = 0; x < room.w; ++x)	
		{
			// don't bother with ignored tiles
			if(room.tiles[y][x][0] == ignored)
				continue;

			// Read the pixel from the grid
			// We only care about layer 0
			int r, g, b, a;

			r = (int)(minimapData[room.tiles[y][x][0]].r * 255);
			g = (int)(minimapData[room.tiles[y][x][0]].g * 255);
			b = (int)(minimapData[room.tiles[y][x][0]].b * 255);
			a = 255;

			// Get our color
			Uint32 color = SDL_MapRGBA(texture->format, r, g, b, a);
			
			// put these pixels on the screen
			Uint32 *pixels = (Uint32 *)texture->pixels;
			pixels[ ( (y + room.y1) * texture->w ) + (x + room.x1) ] = color;

		}

	// unlock the texture
	if( SDL_MUSTLOCK( texture ) )
        SDL_UnlockSurface( texture );



	// Convert the texture to an openGL texture
	//-------------------------------------------------------

	// Convert the surface to a format readable by openGL
	// Basic declarations
	GLenum texture_format;
	GLint nOfColors;	
	
	// get the number of channels in the SDL surface
    nOfColors = texture->format->BytesPerPixel;
    if (nOfColors == 4)     // contains an alpha channel
    {
            if (texture->format->Rmask == 0x000000ff)
                    texture_format = GL_RGBA;
            else
                    texture_format = GL_BGRA;
    } else if (nOfColors == 3)     // no alpha channel
    {
            if (texture->format->Rmask == 0x000000ff)
                    texture_format = GL_RGB;
            else
                    texture_format = GL_BGR;
    } else {
            assert("Loaded image is not truecolor" && false);
    }


	
	// Have OpenGL generate a texture object handle for us
	m_RoomTextureMap.insert(pair<int, GLuint>(room.ID, 0));
	glGenTextures( 1, &m_RoomTextureMap[room.ID] );
 
	// Bind the texture object
	glBindTexture( GL_TEXTURE_2D, m_RoomTextureMap[room.ID] );
 
	// Set the texture's stretching properties
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 
	// Edit the texture object's image data using the information SDL_Surface gives us
	glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, texture->w, texture->h, 0,
                      texture_format, GL_UNSIGNED_BYTE, texture->pixels );



	// Free memory
	SDL_FreeSurface(texture);
}

void Minimap::Remove(const Room& room)
{
	map<int, GLuint>::iterator it, remove;

	bool found = false;
	for(it = m_RoomTextureMap.begin(); it != m_RoomTextureMap.end(); ++it)
	{
		if(it->first == room.ID)
		{
			remove = it;
			found = true;
		}
	}

	if(found)
	{
		glDeleteTextures(1, &remove->second);
		remove->second = 0;
		m_RoomTextureMap.erase(remove);
	}

}
// Create the minimap from already created data
void Minimap::Load(const vector<vector<list<int>>>& map)
{
		// free memory if necessary
	Delete();

	// get map width / height
	m_MapDimensions.h = map.size() - 1;
	m_MapDimensions.w = map[0].size() - 1;
	
	// setup the texture ratio
	m_TextureRatio = (float)m_MapDimensions.h / (float)m_MapDimensions.w;

	// height / width
	vector<int> usedTiles;

	// resize the map
	// read map data
	char buffer[100];
	for(int h = 0; h < m_MapDimensions.h; h++)
		for(int w = 0; w < m_MapDimensions.w; w++)
		{
			// if this tile has not already been added to used tiles then add it
			bool insert = true;
			for(vector<int>::const_iterator iter = usedTiles.begin(); iter != usedTiles.end(); ++iter)
				if(map[h][w].front() == *iter)
					insert = false;

			if(insert)
				usedTiles.push_back(map[h][w].front());
		}

	// load in minimap data
	std::map<int, ImageLoader::MinimapData>	minimapData;
	for(int i = 0; i < usedTiles.size(); ++i)
	{
		minimapData.insert(std::pair<int, ImageLoader::MinimapData>(usedTiles[i],
				(*(ImageManager->GetMinimapData(usedTiles[i])))));
	}
	

	// Create the texture and make it black
	SDL_PixelFormat RGBAFormat = GetPixelFormat();
	SDL_Surface* texture = SDL_CreateRGBSurface( SDL_SWSURFACE, GetNextPowerOfTwo(m_MapDimensions.w), GetNextPowerOfTwo(m_MapDimensions.h), RGBAFormat.BitsPerPixel,
		RGBAFormat.Rmask, RGBAFormat.Gmask, RGBAFormat.Bmask, RGBAFormat.Amask );
	SDL_FillRect(texture, NULL, SDL_MapRGB((const SDL_PixelFormat *const)&RGBAFormat, 255, 255, 255));

	// lock the texture
	if( SDL_MUSTLOCK( texture ) )
        SDL_LockSurface( texture );

	// Create the new minimap texture
	for(int y = 0; y < m_MapDimensions.h; ++y)
		for(int x = 0; x < m_MapDimensions.w; ++x)	
		{
			// Read the pixel from the grid
			// We only care about layer 0
			int r, g, b;

			r = (int)(minimapData[map[y][x].front()].r * 255);
			g = (int)(minimapData[map[y][x].front()].g * 255);
			b = (int)(minimapData[map[y][x].front()].b * 255);

			// apply a smoothing algorithm
			int rl = 0, rt = 0, rr = 0, rb = 0; // red left, red top, red right, red bottom
			int gl = 0, gt = 0, gr = 0, gb = 0; // green left, green top, green right, green bottom
			int bl = 0, bt = 0, br = 0, bb = 0; // blue left, blue top, blue right, blue bottom

			// get colors
			if(x > 0)
			{
				rl = (int)(minimapData[map[y][x-1].front()].r * 255);
				gl = (int)(minimapData[map[y][x-1].front()].g * 255);
				bl = (int)(minimapData[map[y][x-1].front()].b * 255);
			}

			if(y > 0)
			{
				rt = (int)(minimapData[map[y-1][x].front()].r * 255);
				gt = (int)(minimapData[map[y-1][x].front()].g * 255);
				bt = (int)(minimapData[map[y-1][x].front()].b * 255);
			}

			if(x < m_MapDimensions.w - 1)
			{
				rr = (int)(minimapData[map[y][x+1].front()].r * 255);
				gr = (int)(minimapData[map[y][x+1].front()].g * 255);
				br = (int)(minimapData[map[y][x+1].front()].b * 255);
			}
			
			if(y < m_MapDimensions.h - 1)
			{
				rb = (int)(minimapData[map[y+1][x].front()].r * 255);
				gb = (int)(minimapData[map[y+1][x].front()].g * 255);
				bb = (int)(minimapData[map[y+1][x].front()].b * 255);
			}
			
			// Now, we actually smooth the minimap by multiplying the source pixel by a percentage of its surrounding pixels
			float mix = .2;
			r += ((rl + rt + rr + rb) * mix);
			b += ((bl + bt + br + bb) * mix);
			g += ((gl + gt + gr + gb) * mix);

			// SDL doesn't like pixels over 255; ensure they are not over 255
			if(r > 255) r = 255;
			if(b > 255) b = 255;
			if(g > 255) g = 255;

			// Get our color
			Uint32 color = SDL_MapRGB(texture->format, r, g, b);
			
			// put these pixels on the screen
			Uint32 *pixels = (Uint32 *)texture->pixels;
			pixels[ ( y * texture->w ) + x ] = color;

		}

	// unlock the texture
	if( SDL_MUSTLOCK( texture ) )
        SDL_UnlockSurface( texture );



	// Convert the texture to an openGL texture
	//-------------------------------------------------------

	// Convert the surface to a format readable by openGL
	// Basic declarations
	GLenum texture_format;
	GLint nOfColors;	
	
	// get the number of channels in the SDL surface
    nOfColors = texture->format->BytesPerPixel;
    if (nOfColors == 4)     // contains an alpha channel
    {
            if (texture->format->Rmask == 0x000000ff)
                    texture_format = GL_RGBA;
            else
                    texture_format = GL_BGRA;
    } else if (nOfColors == 3)     // no alpha channel
    {
            if (texture->format->Rmask == 0x000000ff)
                    texture_format = GL_RGB;
            else
                    texture_format = GL_BGR;
    } else {
            assert("Loaded image is not truecolor" && false);
    }



	// Have OpenGL generate a texture object handle for us
	glGenTextures( 1, &m_Texture );
 
	// Bind the texture object
	glBindTexture( GL_TEXTURE_2D, m_Texture );
 
	// Set the texture's stretching properties
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 
	// Edit the texture object's image data using the information SDL_Surface gives us
	glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, texture->w, texture->h, 0,
                      texture_format, GL_UNSIGNED_BYTE, texture->pixels );



	// Free memory
	SDL_FreeSurface(texture);

	// We have built the texture
	m_IsBuilt = true;

	// Compute texture position / location
	RecomputeTexturePosition();
	
	// Set up our texture clipping percentages
	m_TextureClippingPercentage.x = double(m_MapDimensions.w) / double(GetNextPowerOfTwo(m_MapDimensions.w));
	m_TextureClippingPercentage.y = double(m_MapDimensions.h) / double(GetNextPowerOfTwo(m_MapDimensions.w));
}
void Minimap::RecomputeTexturePosition()
{
	// Get our values that modify the location of the texture, based on the texture ratio
	int addX = 0, addY = 0;
	if((int)m_TextureRatio < 1)
		addY = (m_TextureDimensions.h * m_TextureRatio);
	else if((int)m_TextureRatio > 1)
		addX = (m_TextureDimensions.w  / m_TextureRatio);

	float multX = 1, multY = 1;
	if((int)m_TextureRatio < 1)
		multY = m_TextureRatio;
	else if((int)m_TextureRatio > 1)
		multX = (1 / m_TextureRatio);

	// Change texture size
	m_TextureDimensions.w = m_OriginalDimensions.w * multX;
	m_TextureDimensions.h = m_OriginalDimensions.h * multY;

	// Set texture position
	m_TexturePosition.x = m_OriginalPosition.x + addX;
	m_TexturePosition.y = m_OriginalPosition.y + addY;
}

// Delete the minimap texture
void Minimap::Delete()
{
	if(m_IsBuilt)
	{
		glDeleteTextures(1, &m_Texture);
		m_Texture = 0; // Nobody likes a dangling pointer.

		m_IsBuilt = false;
	}

	map<int, GLuint>::iterator it;
	for(it = m_RoomTextureMap.begin(); it != m_RoomTextureMap.end(); ++it)
	{
		glDeleteTextures(1, &it->second);
		it->second = 0;
	}
	m_RoomTextureMap.clear();
}

// Returns true if the mouse is in the bounds of the minimap
bool Minimap::inBounds(int x, int y)
{
	if((x >= m_TexturePosition.x) && (x <= (m_TexturePosition.x + m_TextureDimensions.w))
		&& (y >= m_TexturePosition.y) && (y <= (m_TexturePosition.y + m_TextureDimensions.h)))
			return true;

	return false;
}

void Minimap::HandleScrolling(const Vector2D& mouse)
{
    if(inBounds(mouse.x, mouse.y))
	{

		Vector2D pos = mouse;


		pos.x -= m_TexturePosition.x;
		pos.y -= m_TexturePosition.y;
		
		float sizeRatioX = (float)DataLoader->GetMapWidth() / (float)m_TextureDimensions.w;
		float sizeRatioY = (float)DataLoader->GetMapHeight() / (float)m_TextureDimensions.h;

		pos.x *= TILE_DIMENSIONS * sizeRatioX;
		pos.y *= TILE_DIMENSIONS * sizeRatioY;

		int centerX = m_pClipPlane->GetWidth() / 2;
		int centerY = m_pClipPlane->GetHeight() / 2;

		pos.x -= centerX;
		pos.y -= centerY;
		
		m_pClipPlane->SetX(pos.x);
		m_pClipPlane->SetY(pos.y);

		if(m_pClipPlane->GetX() + m_pClipPlane->GetWidth() > DataLoader->GetMapWidth() * TILE_DIMENSIONS)
			m_pClipPlane->SetX((DataLoader->GetMapWidth() * TILE_DIMENSIONS)  - m_pClipPlane->GetWidth());

		if(m_pClipPlane->GetY() + m_pClipPlane->GetHeight() > DataLoader->GetMapHeight() * TILE_DIMENSIONS)
			m_pClipPlane->SetY((DataLoader->GetMapHeight() * TILE_DIMENSIONS) - m_pClipPlane->GetHeight());

		if(m_pClipPlane->GetY() < 0)
			m_pClipPlane->SetY(0);

		if(m_pClipPlane->GetX() < 0)
			m_pClipPlane->SetX(0);
	}
}

Vector2D Minimap::GetWorldPosFromMousePos(const Vector2D& mouse)
{
	Vector2D pos(0, 0);
	if(inBounds(mouse.x, mouse.y))
	{
		pos = mouse;

		pos.x -= m_TexturePosition.x;
		pos.y -= m_TexturePosition.y;
		
		float sizeRatioX = (float)DataLoader->GetMapWidth() / (float)m_TextureDimensions.w;
		float sizeRatioY = (float)DataLoader->GetMapHeight() / (float)m_TextureDimensions.h;

		pos.x *= TILE_DIMENSIONS * sizeRatioX;
		pos.y *= TILE_DIMENSIONS * sizeRatioY;

		int centerX = m_pClipPlane->GetWidth() / 2;
		int centerY = m_pClipPlane->GetHeight() / 2;

		pos.x -= centerX;
		pos.y -= centerY;
		
	}

	return pos;
}

// Rendering functions
void Minimap::RenderMinimap()
{
	// Render our minimap texture
	if(m_IsBuilt)
	{
		// Render our background
		DrawPrimitives->DrawRectangle(m_TexturePosition.x - m_SurroundDistance, m_TexturePosition.y - m_SurroundDistance,
			m_TexturePosition.x + m_TextureDimensions.w + m_SurroundDistance,
			m_TexturePosition.y + m_TextureDimensions.h + m_SurroundDistance, Key->GetColor("000, 000, 000, 255"));

		glTranslatef((GLfloat)(m_TexturePosition.x), (GLfloat)(m_TexturePosition.y), 0.0f);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

		// Bind the texture
		glBindTexture(GL_TEXTURE_2D, m_Texture);

			glBegin(GL_QUADS);
				//Top-left vertex (corner)
				glTexCoord2d( 0, 0 );
				glVertex3f( 0.0f, 0.0f, 0.0f );
				
				//Bottom-left vertex (corner)
				glTexCoord2d( 1.0 * m_TextureClippingPercentage.x, 0 );
				//glTexCoord2i( 1.0, 0 );
				glVertex3f( (float)m_TextureDimensions.w, 0.0f, 0.0f );
				//glVertex3f( 150, 0.0f, 0.0f );
				
				//Bottom-right vertex (corner)
				glTexCoord2d( 1.0 * m_TextureClippingPercentage.x, 1.0 * m_TextureClippingPercentage.y );
				//glTexCoord2i( 1.0, 1.0 );
				glVertex3f( (float)m_TextureDimensions.w, (float)m_TextureDimensions.h, 0.0f );
				//glVertex3f( 150, 150, 0.0f );

				//Top-right vertex (corner)
				glTexCoord2d( 0, 1.0 * m_TextureClippingPercentage.y );
				//glTexCoord2i( 0, 1.0 );
				glVertex3f( 0.0f, (float)m_TextureDimensions.h, 0.0f );
				//glVertex3f( 0.0f, 150, 0.0f );

			glEnd();

		// render all the rooms
		map<int, GLuint>::const_iterator it;
		for(it = m_RoomTextureMap.begin(); it != m_RoomTextureMap.end(); ++it)
		{
			glBindTexture(GL_TEXTURE_2D, it->second);
			glBegin(GL_QUADS);
				//Top-left vertex (corner)
				glTexCoord2d( 0, 0 );
				glVertex3f( 0.0f, 0.0f, 0.0f );
				
				//Bottom-left vertex (corner)
				glTexCoord2d( 1.0 * m_TextureClippingPercentage.x, 0 );
				//glTexCoord2i( 1.0, 0 );
				glVertex3f( (float)m_TextureDimensions.w, 0.0f, 0.0f );
				//glVertex3f( 150, 0.0f, 0.0f );
				
				//Bottom-right vertex (corner)
				glTexCoord2d( 1.0 * m_TextureClippingPercentage.x, 1.0 * m_TextureClippingPercentage.y );
				//glTexCoord2i( 1.0, 1.0 );
				glVertex3f( (float)m_TextureDimensions.w, (float)m_TextureDimensions.h, 0.0f );
				//glVertex3f( 150, 150, 0.0f );

				//Top-right vertex (corner)
				glTexCoord2d( 0, 1.0 * m_TextureClippingPercentage.y );
				//glTexCoord2i( 0, 1.0 );
				glVertex3f( 0.0f, (float)m_TextureDimensions.h, 0.0f );
				//glVertex3f( 0.0f, 150, 0.0f );

			glEnd();
		}

		glLoadIdentity();
	}
}

void Minimap::RenderMinimap(list<Room>* rooms)
{
	// first, we just render the minimap
	RenderMinimap();

	// don't bother rendering rooms if there are none!
	if(rooms->size() == 1)
		return;
	
	glDisable(GL_TEXTURE_2D); // disable textures

	int ignored = ImageManager->GetImageID("ignored_tile");
	glBegin(GL_POINTS);
	// iterate through all of the rooms
	list<Room>::const_iterator it = rooms->begin();
	++it;
	for(; it != rooms->end(); ++it)
	{
		// iterate the height and width of the room
		for(int h = 0; h < (it)->h; ++h)
			for(int w = 0; w < (it)->w; ++w)
			{
				if((it)->tiles[h][w][0] == ignored)
					continue;

				ImageLoader::MinimapData* data = ImageManager->GetMinimapData((it)->tiles[h][w][0]);
				glColor4f(data->r, data->g, data->b, 1.0);
		
				float x, y;

				x = (float)((it)->x1 + w) / (float)(DataLoader->GetMapWidth());
				y = (float)((it)->y1 + h) / (float)(DataLoader->GetMapHeight());
		
				x *= m_TextureDimensions.w;
				y *= m_TextureDimensions.h;

				x += m_TexturePosition.x;
				y += m_TexturePosition.y;


				glVertex3f(x, y, 1.0f);
				glVertex3f(x + 1, y + 1, 1.0f);
				glVertex3f(x, y + 1, 1.0f);
				glVertex3f(x + 1, y, 1.0f);
			}
	}
	glEnd();
	glEnable(GL_TEXTURE_2D);



}
// Render the screen onto the minimap
void Minimap::RenderScreen()
{
	float x, y, w, h;

	// this gets percentages, then we have to multiply to find pixels; the denom appears to specify how far to the right and down the box can go
	x = (float)(m_pClipPlane->GetX() / TILE_DIMENSIONS) / (float)(DataLoader->GetMapWidth() - 2);
	y = (float)(m_pClipPlane->GetY() / TILE_DIMENSIONS) / (float)(DataLoader->GetMapHeight() - 1);
	
	x *= m_TextureDimensions.w;
	y *= m_TextureDimensions.h;

	x += m_TexturePosition.x;// + m_SurroundDistance;
	y += m_TexturePosition.y;// + m_SurroundDistance;

	// window width / height, but shrunken
	w = float(DataLoader->WINDOW_WIDTH) / float((DataLoader->GetMapWidth() * TILE_DIMENSIONS) - 2);
	h = float(DataLoader->WINDOW_HEIGHT) / float((DataLoader->GetMapHeight() * TILE_DIMENSIONS) - 1);

	w *= m_TextureDimensions.w;
	h *= m_TextureDimensions.h;

	// black but not fully faded in
	OGL_Color col;
	col.r = 1;
	col.b = 1;
	col.g = 1;
	col.a = .7;

	// finally, we can render
	DrawPrimitives->DrawRectangle(x, y, x + w, y + h, col);
}

void Minimap::RenderEntities()
{
	map<int, ColoredCoords>::iterator iter;

	glDisable(GL_TEXTURE_2D);
	glLoadIdentity();
	//glTranslatef(minimapStartX, minimapStartY, 1.0f);

	glBegin(GL_POINTS);
	for(iter = m_Entities.begin(); iter != m_Entities.end(); iter++)
	{
		glColor4f(iter->second.color.r, iter->second.color.g, iter->second.color.b, iter->second.color.a);
		
		float x, y;

		x = (float)(iter->second.coords.x / TILE_DIMENSIONS) / (float)(DataLoader->GetMapWidth() - 2);
		y = (float)(iter->second.coords.y / TILE_DIMENSIONS) / (float)(DataLoader->GetMapHeight() - 1);
		
		x *= m_TextureDimensions.w;
		y *= m_TextureDimensions.h;

		x += m_TexturePosition.x;// + m_SurroundDistance;
		y += m_TexturePosition.y;// + m_SurroundDistance;


		glVertex3f(x, y, 1.0f);
		glVertex3f(x + 1, y + 1, 1.0f);
		glVertex3f(x, y + 1, 1.0f);
		glVertex3f(x + 1, y, 1.0f);

	}
	glEnd();
	glEnable(GL_TEXTURE_2D);
	glLoadIdentity();


}

// Add an entity
void Minimap::AddEntity(int ID, const Vector2D& coords, const OGL_Color& color)
{
	ColoredCoords ccord;
	ccord.coords.x = coords.x;
	ccord.coords.y = coords.y;
	ccord.color = color;

	m_Entities.insert(std::pair<int, ColoredCoords>(ID, ccord));
}

// Remove an entity from the entityMap
void Minimap::RemoveEntity(int ID)
{
	m_Entities.erase(ID); // WARNING: POSSIBLE ERROR HERE
}

// Update the given entitiy ID with new coordinates
void Minimap::UpdateEntity(int ID, const Vector2D& coords)
{
	m_Entities[ID].coords.x = coords.x;
	m_Entities[ID].coords.y = coords.y;
}

